﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1.bestFitting
{
    public class Module_Calculate
    {
        /// <summary>
        /// 计算目标增益 和 实际频响增益的差值
        /// </summary>
        /// <param name="Target"></param>
        /// <param name="Current"></param>
        /// <returns></returns>
        public static double[] CalculateDiff(double[] Target, double[] Current)
        {
            var Diff = new double[Target.Length];
            for (int i = 0; i < Target.Length; i++)
            {
                Diff[i] = Target[i] - Current[i];
            }
            return Diff;
        }

        public static double Mean_weight(List<double> vs, double weight)
        {
            var MIN = vs.Min();
            var MAX = vs.Max();
            var Meanvalue = MAX * weight + MIN * (1 - weight);
            return Math.Ceiling(Meanvalue);
        }

        public static double Mean_weight(List<double> vs)
        {
            var Meanvalue = vs.Average();
            return Math.Ceiling(Meanvalue);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="XList">基准横坐标数据 列表</param>
        /// <param name="YList">基准纵坐标数据 列表</param>
        /// <param name="XList_Target">目标横坐标数据 列表</param>
        /// <returns>目标纵坐标数据</returns>
        public static double[] Interpolation(double[] XList, double[] YList, double[] XList_Target)
        {
            var TargetYList = new double[XList_Target.Length];
            var XLength = XList.Length;
            for (int i = 0; i < XList_Target.Length; i++)
            {
                var X_Target = XList_Target[i];
                double X1, X2, Y1, Y2;
                if (X_Target < XList[0])
                {
                    X1 = XList[0];
                    X2 = XList[1];
                    Y1 = YList[0];
                    Y2 = YList[1];
                    TargetYList[i] = Y1 + ((Y2 - Y1) / (X2 - X1)) * (X_Target - X1);
                    continue;
                }
                if (X_Target > XList[XLength - 1])
                {
                    X1 = XList[XLength - 2];
                    X2 = XList[XLength - 1];
                    Y1 = YList[XLength - 2];
                    Y2 = YList[XLength - 1];
                    TargetYList[i] = Y1 + ((Y2 - Y1) / (X2 - X1)) * (X_Target - X1);
                    continue;
                }
                for (int j = 0; j < XList.Length - 1; j++)
                {
                    var XIndex = XList[j];
                    var XNext = XList[j + 1];
                    if (X_Target == XIndex)
                    {
                        TargetYList[i] = YList[j];
                        break;
                    }
                    if (X_Target == XNext)
                    {
                        TargetYList[i] = YList[j + 1];
                        break;
                    }
                    if (X_Target > XIndex && X_Target < XNext)
                    {
                        X1 = XIndex;
                        X2 = XNext;
                        Y1 = YList[j];
                        Y2 = YList[j + 1];
                        TargetYList[i] = Y1 + ((Y2 - Y1) / (X2 - X1)) * (X_Target - X1);
                        break;
                    }
                }
            }
            return TargetYList;
        }

        public static void InterpolationTarget50(double X1, double[] Value1, double X2, double[] Value2, double Target, out double[] TargetValue)
        {
            int Length = Value1.Length;
            TargetValue = new double[Length];
            for (int i = 0; i < Length; i++)
            {
                var Y1 = Value1[i];
                var Y2 = Value2[i];
                TargetValue[i] = ((Y2 - Y1) / (X2 - X1)) * (Target-X1) + Y1;
            }
        }
        public static void Interpolation(double[] SourceFreq, double[] SourceValue, double[] TargetFreq,out double[] TargetValue)
		{
			int LenIn = SourceFreq.Length;
			int LenOut = TargetFreq.Length;
			int Fs = 16000;
			TargetValue = new double[LenOut];
			int NearFreLow = 0;
			int NearFreHigh = 0;
			double sum;
			int n;

			int Density = 32;
			int F_Max_L = Fs / 2;
			FreInterpolation2(SourceFreq, SourceValue, F_Max_L, Density, LenIn, out double[] Res_Output);

			TargetValue[0] = Res_Output[Math.Max(Convert.ToInt32(Math.Round(TargetFreq[0] / Density, MidpointRounding.AwayFromZero) - 1), 0)];
			TargetValue[1] = Res_Output[Convert.ToInt32(Math.Round(TargetFreq[1] / Density, MidpointRounding.AwayFromZero) - 1)];
			TargetValue[2] = Res_Output[Convert.ToInt32(Math.Round(TargetFreq[2] / Density, MidpointRounding.AwayFromZero) - 1)];
			TargetValue[3] = Res_Output[Convert.ToInt32(Math.Round(TargetFreq[3] / Density, MidpointRounding.AwayFromZero) - 1)];

			for (int i = 4; i < LenOut - 1; i++)
			{
				NearFreLow = Convert.ToInt32(Math.Floor((TargetFreq[i - 1] + TargetFreq[i]) / 2 / Density));
				NearFreHigh = Convert.ToInt32(Math.Floor((TargetFreq[i] + TargetFreq[i + 1]) / 2 / Density));
				sum = 0;
				n = 0;
				for (int j = NearFreLow - 1; j <= NearFreHigh - 1; j++)
				{
					sum += Res_Output[j];
					n++;
				}

				TargetValue[i] = sum / n;
			}

			NearFreLow = NearFreHigh;

			NearFreHigh = ((Fs / 2) / Density);

			sum = 0;
			n = 0;
			for (int j = NearFreLow - 1; j <= NearFreHigh - 1; j++)
			{
				sum += Res_Output[j];
				n++;
			}
			TargetValue[LenOut - 1] = sum / n;


		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="Fre_in"></param>
		/// <param name="DB_in"></param>
		/// <param name="F_Max_L"></param>
		/// <param name="Density"></param>
		/// <param name="Len"></param>
		/// <param name="Res_Output"></param>
		public static void FreInterpolation2(double[] Fre_in, double[] DB_in, int F_Max_L, int Density, int Len, out double[] Res_Output)
		{
            int L = F_Max_L / Density;
            Res_Output = new double[L];
			double fre_max = Fre_in[0];
			double fre_min = 0;
			var index = 0;

            int i;
            for (i = 0; i < L; i++)
            {
                if ((i + 1) * Density <= Fre_in[0])
                {
                    Res_Output[i] = DB_in[0] - (DB_in[1] - DB_in[0]) / (Fre_in[1] - Fre_in[0]) * (Fre_in[0] - i * Density);
                }
                else if ((i + 1) * Density >= Fre_in[Len - 1])
                {
                    Res_Output[i] = DB_in[Len - 1] - (DB_in[Len - 1] - DB_in[Len - 2]) / (Fre_in[Len - 1] - Fre_in[Len - 2]) * (Fre_in[Len - 1] - (i + 1) * Density);
                }
                else
                {
                    if ((i + 1) * Density > fre_max)
                    {
                        while ((i + 1) * Density > fre_max)
                        {
                            index++;
                            fre_min = fre_max;
                            fre_max = Fre_in[index];
                        }

                    }

                    Res_Output[i] = ((i + 1) * Density - fre_min) / (fre_max - fre_min) * DB_in[index] + (fre_max - (i + 1) * Density) / (fre_max - fre_min) * DB_in[index - 1];
                }
            }

        }
	}
}
